package com.yunhe.authority.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import com.github.stuxuhai.jpinyin.PinyinException;
import com.yunhe.authority.model.poi.CompanyPoi;
import com.yunhe.authority.service.company.CompanyService;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.ModelNotFoundException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UniqueConstraintsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author: DongWenYu
 * @Date: 2021/2/24 15:05
 * 有个很重要的点 UploadDataListener 不能被spring管理，要每次读取excel都要new,然后里面用到spring可以构造方法传进去
 */
public class NewUploadDataListener extends AnalysisEventListener<CompanyPoi> {

    private static final Logger logger = LoggerFactory.getLogger(NewUploadDataListener.class);

    /**
     * 实际使用中可以3000条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 3000;
    List<CompanyPoi> list = new ArrayList<CompanyPoi>();

    private CompanyService companyService;

    /**
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     * @param companyService
     * @return
     * @create 2021/2/23 11:24
     */
    public NewUploadDataListener(CompanyService companyService) {
        this.companyService = companyService;
    }

    /**
     * 这个每一条数据解析都会来调用
     * @param data
     * @param context
     * @return void
     * @create 2021/2/23 11:26
     */
    @Override
    public void invoke(CompanyPoi data, AnalysisContext context) {
        logger.debug("解析到一条数据:{}", JSON.toJSONString(data));
        list.add(data);
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (list.size() >= BATCH_COUNT) {
            try {
                saveData();
            } catch (UniqueConstraintsException | ObjectNotFoundException | ArgumentErrorException | PinyinException | ModelNotFoundException e) {
                logger.error(String.valueOf(e.getMessage()));
            }
            // 存储完成清理 list
            list.clear();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        try {
            saveData();
        } catch (UniqueConstraintsException | ObjectNotFoundException | ArgumentErrorException | PinyinException | ModelNotFoundException e) {
            logger.error(String.valueOf(e.getMessage()));
        }
        logger.info("所有数据解析完成！");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() throws UniqueConstraintsException, ObjectNotFoundException, ArgumentErrorException, PinyinException, ModelNotFoundException {
        logger.info("{}条数据，开始存储数据库！", list.size());
        companyService.importCompanyExcel(list);
    }
}